using System;
using System.IO;
using System.Globalization;
using System.Text;
using Newtonsoft.Json;

namespace SafeShrink
{
    /// <summary>
    /// 日志记录器类，负责应用程序的日志记录功能
    /// </summary>
    public class Logger : IDisposable
    {
        private readonly string logDirectory;
        private readonly int maxLogSizeMB = 10;
        private readonly LogLevel minLogLevel = LogLevel.Info;
        private readonly SemaphoreSlim logLock = new SemaphoreSlim(1, 1);
        private StreamWriter? logWriter;
        private string? currentLogFile;
        
        /// <summary>
        /// 日志级别枚举
        /// </summary>
        public enum LogLevel
        {
            Debug,
            Info,
            Warning,
            Error
        }

        /// <summary>
        /// 构造函数，初始化日志目录
        /// </summary>
        public Logger(LogLevel minLevel = LogLevel.Info, int maxSizeMB = 10)
        {
            minLogLevel = minLevel;
            maxLogSizeMB = maxSizeMB;
            
            // 创建按日期组织的日志目录
            logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, 
                                      "Logs", 
                                      DateTime.Now.ToString("yyyy-MM-dd"));
            
            Directory.CreateDirectory(logDirectory);  // 确保目录存在
            InitializeLogWriter();
        }

        private void InitializeLogWriter()
        {
            const int maxRetries = 3;
            int retryCount = 0;
            
            while (retryCount < maxRetries)
            {
                try
                {
                    // 生成带时间戳的日志文件名，避免冲突
                    currentLogFile = Path.Combine(logDirectory, $"log_{DateTime.Now:HHmmss}.txt");
                    
                    // 确保目录存在
                    Directory.CreateDirectory(logDirectory);
                    
                    // 尝试创建新文件而不是追加
                    logWriter = new StreamWriter(currentLogFile, false, System.Text.Encoding.UTF8)
                    {
                        AutoFlush = true
                    };
                    
                    // 写入初始日志头
                    logWriter.WriteLine($"=== 日志会话开始于 {DateTime.Now} ===");
                    return;
                }
                catch (IOException ex)
                {
                    retryCount++;
                    if (retryCount >= maxRetries)
                    {
                        // 作为最后手段，回退到控制台日志
                        Console.WriteLine($"警告: 无法创建日志文件 {currentLogFile}, 将使用控制台日志");
                        logWriter = new StreamWriter(Console.OpenStandardOutput())
                        {
                            AutoFlush = true
                        };
                        return;
                    }
                    
                    // 等待一段时间后重试
                    Thread.Sleep(100 * retryCount);
                }
                catch (UnauthorizedAccessException ex)
                {
                    throw new Exception($"没有权限访问日志文件: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 记录调试级别日志
        /// </summary>
        public void LogDebug(string message) => LogAsync(LogLevel.Debug, message).Wait();

        /// <summary>
        /// 记录信息级别日志
        /// </summary>
        public void LogInfo(string message) => LogAsync(LogLevel.Info, message).Wait();

        /// <summary>
        /// 记录警告级别日志
        /// </summary>
        public void LogWarning(string message) => LogAsync(LogLevel.Warning, message).Wait();

        /// <summary>
        /// 记录错误级别日志
        /// </summary>
        public void LogError(string message) => LogAsync(LogLevel.Error, message).Wait();

        /// <summary>
        /// 异步记录日志
        /// </summary>
        public async Task LogAsync(LogLevel level, string message)
        {
            if (level < minLogLevel) return;
            
            try
            {
                await logLock.WaitAsync();
                
                // 检查是否需要切换日志文件(跨小时或文件过大)
                if (DateTime.Now.Hour != new FileInfo(currentLogFile).CreationTime.Hour ||
                    new FileInfo(currentLogFile).Length > maxLogSizeMB * 1024 * 1024)
                {
                    logWriter.Dispose();
                    InitializeLogWriter();
                }
                
                string logEntry = JsonConvert.SerializeObject(new
                {
                    Timestamp = DateTime.UtcNow.ToString("O"),
                    Level = level.ToString(),
                    Message = message,
                    ThreadId = Thread.CurrentThread.ManagedThreadId
                });
                
                await logWriter.WriteLineAsync(logEntry);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"日志写入失败: {ex.Message}");
                Console.WriteLine($"[{level}] {message}");
            }
            finally
            {
                logLock.Release();
            }
        }

        public void Dispose()
        {
            logWriter?.Dispose();
            logLock?.Dispose();
            GC.SuppressFinalize(this);
        }

        ~Logger()
        {
            Dispose();
        }
    }
}